/*
 * Copyright 2013 GiavaCms.org.
 *
 * Licensed under the Eclipse Public License version 1.0, available at
 * http://www.eclipse.org/legal/epl-v10.html
 */
package org.giavacms.common.servlet;

import java.net.URL;

import javax.servlet.ServletConfig;
import javax.servlet.ServletContext;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.giavacms.common.util.FileUtils;
import org.jboss.logging.Logger;


/**
 * 
 * 
 * @author pisi79
 * 
 */
abstract public class DownloadServlet<T> extends HttpServlet
{

   private static final long serialVersionUID = 1L;

   protected Logger logger = Logger.getLogger(getClass());

   ServletContext ctx;

   @Override
   public void init(ServletConfig config) throws ServletException
   {
      super.init(config);
      ctx = config.getServletContext();
   }

   @Override
   protected void service(HttpServletRequest req, HttpServletResponse resp)
   {

      try
      {
         String uri = req.getRequestURI();
         if (uri.indexOf("?") >= 0)
         {
            uri.substring(0, uri.indexOf("?"));
         }
         String parts[] = uri.split("/");
         String filename = parts[parts.length - 1];
         String id = parts[parts.length - 2];

         T object = fetch(id, req, resp);
         byte[] bytes = getBytes(object, req, resp);
         String contentType = getContentType(object, filename);

         // Init servlet response.
         resp.setHeader("Content-Type", contentType);
         resp.setHeader("Content-Length", String.valueOf(bytes.length));
         if (isForceDownload())
         {
            resp.setHeader("Content-Disposition", "attachment; filename=\"" + filename + "\"");
         }
         else
         {
            resp.setHeader("Content-Disposition", "inline; filename=\""
                     + filename + "\"");
         }

         boolean result = FileUtils.writeBytesToOutputStream(
                  resp.getOutputStream(), bytes);

         if (!result)
         {
            throw new RuntimeException(
                     "Errore nella scrittura sullo stream di output!");
         }
      }
      catch (Exception e)
      {
         throw new RuntimeException(
                  "Errore nella lettura dello stream di input!");
      }

   }

   protected boolean isForceDownload()
   {
      return false;
   }

   public void destroy()
   {
   }

   /**
    * PostScript ai eps ps application/postscript Microsoft Rich Text Format rtf application/rtf Adobe Acrobat PDF pdf
    * application/pdf application/x-pdf Maker Interchange Format (FrameMaker) mif application/vnd.mif application/x-mif
    * Troff document t tr roff application/x-troff Troff document with MAN macros man application/x-troff-man Troff
    * document with ME macros me application/x-troff-me Troff document with MS macros ms application/x-troff-ms LaTeX
    * document latex application/x-latex Tex/LateX document tex application/x-tex GNU TexInfo document texinfo texi
    * application/x-texinfo TeX dvi format dvi application/x-dvi MacWrite document ?? application/macwriteii MS word
    * document ?? application/msword WordPerfect 5.1 document ?? application/wordperfect5.1 SGML application (RFC 1874)
    * application/sgml Office Document Architecture oda application/oda Envoy Document evy application/envoy
    * 
    * @param filename
    * @return
    */
   protected String getContentType(T object, String filename)
   {
      if (filename == null || filename.equals(""))
      {
         return "text/html";
      }
      else if (filename.toLowerCase().endsWith(".pdf"))
      {
         return "application/pdf";
      }
      else if (filename.toLowerCase().endsWith(".rtf"))
      {
         return "application/rtf";
      }
      else if (filename.toLowerCase().endsWith(".doc") || filename.toLowerCase().endsWith(".docx"))
      {
         return "application/msword";
      }
      else if (filename.toLowerCase().endsWith(".xls"))
      {
         return "application/excel";
      }
      else if (filename.toLowerCase().endsWith(".zip"))
      {
         return "application/zip";
      }
      else if (filename.toLowerCase().endsWith(".xml"))
      {
         return "text/xml";
      }
      // application/vnd.openxmlformats .docx .pptx .xlsx .xltx . xltm .dotx
      // .potx .ppsx
      else if (filename.toLowerCase().endsWith(".docx") || filename.toLowerCase().endsWith(".pptx")
               || filename.toLowerCase().endsWith(".xlsx") || filename.toLowerCase().endsWith(".xltx")
               || filename.toLowerCase().endsWith(".xltm") || filename.toLowerCase().endsWith(".dotx")
               || filename.toLowerCase().endsWith(".potx") || filename.toLowerCase().endsWith(".ppsx"))
      {
         return "application/vnd.openxmlformats";
      }
      else if (filename.toLowerCase().endsWith(".jpg") || filename.toLowerCase().endsWith(".jpeg"))
      {
         return "image/jpeg";
      }
      else if (filename.toLowerCase().endsWith(".png"))
      {
         return "image/png";
      }
      else if (filename.toLowerCase().endsWith(".gif"))
      {
         return "image/gif";
      }
      else if (filename.toLowerCase().endsWith(".tif") || filename.toLowerCase().endsWith(".tiff"))
      {
         return "image/tiff";
      }
      else if (filename.toLowerCase().endsWith(".bmp"))
      {
         return "image/bmp";
      }

      return "text/html";
   }

   protected byte[] getBytesFromUrlAsString(String urlString)
   {
      try
      {
         URL url = new URL(urlString);
         return FileUtils.getBytesFromUrl(url);
      }
      catch (Exception e)
      {
         logger.error(e.getMessage(), e);
         return null;
      }
   }

   /**
    * Implementa questo metodo per resituire i byte del documento a partire dall'oggetto su db
    * 
    * nel caso il documento su db non abbia il bytearray tra i suoi campi, ma indichi un url da cui scaricare si può
    * usare il metodo getBytesFromUrlAsString() di questa classe per farlo
    * 
    * override this... se c'è bisogno di recuperare oggetti dalla sessione
    */
   abstract protected byte[] getBytes(T object, HttpServletRequest req,
            HttpServletResponse resp);

   /**
    * implementa questo metodo per rendere la servlet capace di recuperare l'oggetto da db a partire dal suo id
    * (ricevuto come stringa all'interno dei parametri di richiesta)
    * 
    * ignore req and rest ... se non c'è bisogno di recuperare oggetti dalla sessione
    */
   abstract protected T fetch(String id, HttpServletRequest req,
            HttpServletResponse resp);

   /*
    * Estensione
    * 
    * MIME type
    * 
    * .3dm x-world/x-3dmf .3dmf x-world/x-3dmf .a application/octet-stream .aab application/x-authorware-bin .aam
    * application/x-authorware-map .aas application/x-authorware-seg .abc text/vnd.abc .acgi text/html .afl
    * video/animaflex .ai application/postscript .aif audio/aiff .aif audio/x-aiff .aifc audio/aiff .aifc audio/x-aiff
    * .aiff audio/aiff .aiff audio/x-aiff .aim application/x-aim .aip text/x-audiosoft-intra .ani
    * application/x-navi-animation .aos application/x-nokia-9000-communicator-add-on-software .aps application/mime .arc
    * application/octet-stream .arj application/arj .arj application/octet-stream .art image/x-jg .asf video/x-ms-asf
    * .asm text/x-asm .asp text/asp .asx application/x-mplayer2 .asx video/x-ms-asf .asx video/x-ms-asf-plugin .au
    * audio/basic .au audio/x-au .avi application/x-troff-msvideo .avi video/avi .avi video/msvideo .avi video/x-msvideo
    * .avs video/avs-video .bcpio application/x-bcpio .bin application/mac-binary .bin application/macbinary .bin
    * application/octet-stream .bin application/x-binary .bin application/x-macbinary .bm image/bmp .bmp image/bmp .bmp
    * image/x-windows-bmp .boo application/book .book application/book .boz application/x-bzip2 .bsh application/x-bsh
    * .bz application/x-bzip .bz2 application/x-bzip2 .c text/plain .c text/x-c .c++ text/plain .cat
    * application/vnd.ms-pki.seccat .cc text/plain .cc text/x-c .ccad application/clariscad .cco application/x-cocoa
    * .cdf application/cdf .cdf application/x-cdf .cdf application/x-netcdf .cer application/pkix-cert .cer
    * application/x-x509-ca-cert .cha application/x-chat .chat application/x-chat .class application/java .class
    * application/java-byte-code .class application/x-java-class .com application/octet-stream .com text/plain .conf
    * text/plain .cpio application/x-cpio .cpp text/x-c .cpt application/mac-compactpro .cpt application/x-compactpro
    * .cpt application/x-cpt .crl application/pkcs-crl .crl application/pkix-crl .crt application/pkix-cert .crt
    * application/x-x509-ca-cert .crt application/x-x509-user-cert .csh application/x-csh .csh text/x-script.csh .css
    * application/x-pointplus .css text/css .cxx text/plain .dcr application/x-director .deepv application/x-deepv .def
    * text/plain .der application/x-x509-ca-cert .dif video/x-dv .dir application/x-director .dl video/dl .dl video/x-dl
    * .doc application/msword .dot application/msword .dp application/commonground .drw application/drafting .dump
    * application/octet-stream .dv video/x-dv .dvi application/x-dvi .dwf drawing/x-dwf (old) .dwf model/vnd.dwf .dwg
    * application/acad .dwg image/vnd.dwg .dwg image/x-dwg .dxf application/dxf .dxf image/vnd.dwg .dxf image/x-dwg .dxr
    * application/x-director .el text/x-script.elisp .elc application/x-bytecode.elisp (compiled elisp) .elc
    * application/x-elc .env application/x-envoy .eps application/postscript .es application/x-esrehber .etx
    * text/x-setext .evy application/envoy .evy application/x-envoy .exe application/octet-stream .f text/plain .f
    * text/x-fortran .f77 text/x-fortran .f90 text/plain .f90 text/x-fortran .fdf application/vnd.fdf .fif
    * application/fractals .fif image/fif .fli video/fli .fli video/x-fli .flo image/florian .flx text/vnd.fmi.flexstor
    * .fmf video/x-atomic3d-feature .for text/plain .for text/x-fortran .fpx image/vnd.fpx .fpx image/vnd.net-fpx .frl
    * application/freeloader .funk audio/make .g text/plain .g3 image/g3fax .gif image/gif .gl video/gl .gl video/x-gl
    * .gsd audio/x-gsm .gsm audio/x-gsm .gsp application/x-gsp .gss application/x-gss .gtar application/x-gtar .gz
    * application/x-compressed .gz application/x-gzip .gzip application/x-gzip .gzip multipart/x-gzip .h text/plain .h
    * text/x-h .hdf application/x-hdf .help application/x-helpfile .hgl application/vnd.hp-hpgl .hh text/plain .hh
    * text/x-h .hlb text/x-script .hlp application/hlp .hlp application/x-helpfile .hlp application/x-winhelp .hpg
    * application/vnd.hp-hpgl .hpgl application/vnd.hp-hpgl .hqx application/binhex .hqx application/binhex4 .hqx
    * application/mac-binhex .hqx application/mac-binhex40 .hqx application/x-binhex40 .hqx application/x-mac-binhex40
    * .hta application/hta .htc text/x-component .htm text/html .html text/html .htmls text/html .htt text/webviewhtml
    * .htx text/html .ice x-conference/x-cooltalk .ico image/x-icon .idc text/plain .ief image/ief .iefs image/ief .iges
    * application/iges .iges model/iges .igs application/iges .igs model/iges .ima application/x-ima .imap
    * application/x-httpd-imap .inf application/inf .ins application/x-internett-signup .ip application/x-ip2 .isu
    * video/x-isvideo .it audio/it .iv application/x-inventor .ivr i-world/i-vrml .ivy application/x-livescreen .jam
    * audio/x-jam .jav text/plain .jav text/x-java-source .java text/plain .java text/x-java-source .jcm
    * application/x-java-commerce .jfif image/jpeg .jfif image/pjpeg .jfif-tbnl image/jpeg .jpe image/jpeg .jpe
    * image/pjpeg .jpeg image/jpeg .jpeg image/pjpeg .jpg image/jpeg .jpg image/pjpeg .jps image/x-jps .js
    * application/x-javascript .jut image/jutvision .kar audio/midi .kar music/x-karaoke .ksh application/x-ksh .ksh
    * text/x-script.ksh .la audio/nspaudio .la audio/x-nspaudio .lam audio/x-liveaudio .latex application/x-latex .lha
    * application/lha .lha application/octet-stream .lha application/x-lha .lhx application/octet-stream .list
    * text/plain .lma audio/nspaudio .lma audio/x-nspaudio .log text/plain .lsp application/x-lisp .lsp
    * text/x-script.lisp .lst text/plain .lsx text/x-la-asf .ltx application/x-latex .lzh application/octet-stream .lzh
    * application/x-lzh .lzx application/lzx .lzx application/octet-stream .lzx application/x-lzx .m text/plain .m
    * text/x-m .m1v video/mpeg .m2a audio/mpeg .m2v video/mpeg .m3u audio/x-mpequrl .man application/x-troff-man .map
    * application/x-navimap .mar text/plain .mbd application/mbedlet .mc$ application/x-magic-cap-package-1.0 .mcd
    * application/mcad .mcd application/x-mathcad .mcf image/vasa .mcf text/mcf .mcp application/netmc .me
    * application/x-troff-me .mht message/rfc822 .mhtml message/rfc822 .mid application/x-midi .mid audio/midi .mid
    * audio/x-mid .mid audio/x-midi .mid music/crescendo .mid x-music/x-midi .midi application/x-midi .midi audio/midi
    * .midi audio/x-mid .midi audio/x-midi .midi music/crescendo .midi x-music/x-midi .mif application/x-frame .mif
    * application/x-mif .mime message/rfc822 .mime www/mime .mjf audio/x-vnd.audioexplosion.mjuicemediafile .mjpg
    * video/x-motion-jpeg .mm application/base64 .mm application/x-meme .mme application/base64 .mod audio/mod .mod
    * audio/x-mod .moov video/quicktime .mov video/quicktime .movie video/x-sgi-movie .mp2 audio/mpeg .mp2 audio/x-mpeg
    * .mp2 video/mpeg .mp2 video/x-mpeg .mp2 video/x-mpeq2a .mp3 audio/mpeg3 .mp3 audio/x-mpeg-3 .mp3 video/mpeg .mp3
    * video/x-mpeg .mpa audio/mpeg .mpa video/mpeg .mpc application/x-project .mpe video/mpeg .mpeg video/mpeg .mpg
    * audio/mpeg .mpg video/mpeg .mpga audio/mpeg .mpp application/vnd.ms-project .mpt application/x-project .mpv
    * application/x-project .mpx application/x-project .mrc application/marc .ms application/x-troff-ms .mv
    * video/x-sgi-movie .my audio/make .mzz application/x-vnd.audioexplosion.mzz .nap image/naplps .naplps image/naplps
    * .nc application/x-netcdf .ncm application/vnd.nokia.configuration-message .nif image/x-niff .niff image/x-niff
    * .nix application/x-mix-transfer .nsc application/x-conference .nvd application/x-navidoc .o
    * application/octet-stream .oda application/oda .omc application/x-omc .omcd application/x-omcdatamaker .omcr
    * application/x-omcregerator .p text/x-pascal .p10 application/pkcs10 .p10 application/x-pkcs10 .p12
    * application/pkcs-12 .p12 application/x-pkcs12 .p7a application/x-pkcs7-signature .p7c application/pkcs7-mime .p7c
    * application/x-pkcs7-mime .p7m application/pkcs7-mime .p7m application/x-pkcs7-mime .p7r
    * application/x-pkcs7-certreqresp .p7s application/pkcs7-signature .part application/pro_eng .pas text/pascal .pbm
    * image/x-portable-bitmap .pcl application/vnd.hp-pcl .pcl application/x-pcl .pct image/x-pict .pcx image/x-pcx .pdb
    * chemical/x-pdb .pdf application/pdf .pfunk audio/make .pfunk audio/make.my.funk .pgm image/x-portable-graymap .pgm
    * image/x-portable-greymap .pic image/pict .pict image/pict .pkg application/x-newton-compatible-pkg .pko
    * application/vnd.ms-pki.pko .pl text/plain .pl text/x-script.perl .plx application/x-pixclscript .pm
    * image/x-xpixmap .pm text/x-script.perl-module .pm4 application/x-pagemaker .pm5 application/x-pagemaker .png
    * image/png .pnm application/x-portable-anymap .pnm image/x-portable-anymap .pot application/mspowerpoint .pot
    * application/vnd.ms-powerpoint .pov model/x-pov .ppa application/vnd.ms-powerpoint .ppm image/x-portable-pixmap
    * .pps application/mspowerpoint .pps application/vnd.ms-powerpoint .ppt application/mspowerpoint .ppt
    * application/powerpoint .ppt application/vnd.ms-powerpoint .ppt application/x-mspowerpoint .ppz
    * application/mspowerpoint .pre application/x-freelance .prt application/pro_eng .ps application/postscript .psd
    * application/octet-stream .pvu paleovu/x-pv .pwz application/vnd.ms-powerpoint .py text/x-script.phyton .pyc
    * applicaiton/x-bytecode.python .qcp audio/vnd.qcelp .qd3 x-world/x-3dmf .qd3d x-world/x-3dmf .qif image/x-quicktime
    * .qt video/quicktime .qtc video/x-qtc .qti image/x-quicktime .qtif image/x-quicktime .ra audio/x-pn-realaudio .ra
    * audio/x-pn-realaudio-plugin .ra audio/x-realaudio .ram audio/x-pn-realaudio .ras application/x-cmu-raster .ras
    * image/cmu-raster .ras image/x-cmu-raster .rast image/cmu-raster .rexx text/x-script.rexx .rf
    * image/vnd.rn-realflash .rgb image/x-rgb .rm application/vnd.rn-realmedia .rm audio/x-pn-realaudio .rmi audio/mid
    * .rmm audio/x-pn-realaudio .rmp audio/x-pn-realaudio .rmp audio/x-pn-realaudio-plugin .rng
    * application/ringing-tones .rng application/vnd.nokia.ringing-tone .rnx application/vnd.rn-realplayer .roff
    * application/x-troff .rp image/vnd.rn-realpix .rpm audio/x-pn-realaudio-plugin .rt text/richtext .rt
    * text/vnd.rn-realtext .rtf application/rtf .rtf application/x-rtf .rtf text/richtext .rtx application/rtf .rtx
    * text/richtext .rv video/vnd.rn-realvideo .s text/x-asm .s3m audio/s3m .saveme application/octet-stream .sbk
    * application/x-tbook .scm application/x-lotusscreencam .scm text/x-script.guile .scm text/x-script.scheme .scm
    * video/x-scm .sdml text/plain .sdp application/sdp .sdp application/x-sdp .sdr application/sounder .sea
    * application/sea .sea application/x-sea .set application/set .sgm text/sgml .sgm text/x-sgml .sgml text/sgml .sgml
    * text/x-sgml .sh application/x-bsh .sh application/x-sh .sh application/x-shar .sh text/x-script.sh .shar
    * application/x-bsh .shar application/x-shar .shtml text/html .shtml text/x-server-parsed-html .sid audio/x-psid
    * .sit application/x-sit .sit application/x-stuffit .skd application/x-koan .skm application/x-koan .skp
    * application/x-koan .skt application/x-koan .sl application/x-seelogo .smi application/smil .smil application/smil
    * .snd audio/basic .snd audio/x-adpcm .sol application/solids .spc application/x-pkcs7-certificates .spc
    * text/x-speech .spl application/futuresplash .spr application/x-sprite .sprite application/x-sprite .src
    * application/x-wais-source .ssi text/x-server-parsed-html .ssm application/streamingmedia .sst
    * application/vnd.ms-pki.certstore .step application/step .stl application/sla .stl application/vnd.ms-pki.stl .stl
    * application/x-navistyle .stp application/step .sv4cpio application/x-sv4cpio .sv4crc application/x-sv4crc .svf
    * image/vnd.dwg .svf image/x-dwg .svr application/x-world .svr x-world/x-svr .swf application/x-shockwave-flash .t
    * application/x-troff .talk text/x-speech .tar application/x-tar .tbk application/toolbook .tbk application/x-tbook
    * .tcl application/x-tcl .tcl text/x-script.tcl .tcsh text/x-script.tcsh .tex application/x-tex .texi
    * application/x-texinfo .texinfo application/x-texinfo .text application/plain .text text/plain .tgz
    * application/gnutar .tgz application/x-compressed .tif image/tiff .tif image/x-tiff .tiff image/tiff .tiff
    * image/x-tiff .tr application/x-troff .tsi audio/tsp-audio .tsp application/dsptype .tsp audio/tsplayer .tsv
    * text/tab-separated-values .turbot image/florian .txt text/plain .uil text/x-uil .uni text/uri-list .unis
    * text/uri-list .unv application/i-deas .uri text/uri-list .uris text/uri-list .ustar application/x-ustar .ustar
    * multipart/x-ustar .uu application/octet-stream .uu text/x-uuencode .uue text/x-uuencode .vcd application/x-cdlink
    * .vcs text/x-vcalendar .vda application/vda .vdo video/vdo .vew application/groupwise .viv video/vivo .viv
    * video/vnd.vivo .vivo video/vivo .vivo video/vnd.vivo .vmd application/vocaltec-media-desc .vmf
    * application/vocaltec-media-file .voc audio/voc .voc audio/x-voc .vos video/vosaic .vox audio/voxware .vqe
    * audio/x-twinvq-plugin .vqf audio/x-twinvq .vql audio/x-twinvq-plugin .vrml application/x-vrml .vrml model/vrml
    * .vrml x-world/x-vrml .vrt x-world/x-vrt .vsd application/x-visio .vst application/x-visio .vsw application/x-visio
    * .w60 application/wordperfect6.0 .w61 application/wordperfect6.1 .w6w application/msword .wav audio/wav .wav
    * audio/x-wav .wb1 application/x-qpro .wbmp image/vnd.wap.wbmp .web application/vnd.xara .wiz application/msword
    * .wk1 application/x-123 .wmf windows/metafile .wml text/vnd.wap.wml .wmlc application/vnd.wap.wmlc .wmls
    * text/vnd.wap.wmlscript .wmlsc application/vnd.wap.wmlscriptc .word application/msword .wp application/wordperfect
    * .wp5 application/wordperfect .wp5 application/wordperfect6.0 .wp6 application/wordperfect .wpd
    * application/wordperfect .wpd application/x-wpwin .wq1 application/x-lotus .wri application/mswrite .wri
    * application/x-wri .wrl application/x-world .wrl model/vrml .wrl x-world/x-vrml .wrz model/vrml .wrz x-world/x-vrml
    * .wsc text/scriplet .wsrc application/x-wais-source .wtk application/x-wintalk .xbm image/x-xbitmap .xbm
    * image/x-xbm .xbm image/xbm .xdr video/x-amt-demorun .xgz xgl/drawing .xif image/vnd.xiff .xl application/excel
    * .xla application/excel .xla application/x-excel .xla application/x-msexcel .xlb application/excel .xlb
    * application/vnd.ms-excel .xlb application/x-excel .xlc application/excel .xlc application/vnd.ms-excel .xlc
    * application/x-excel .xld application/excel .xld application/x-excel .xlk application/excel .xlk
    * application/x-excel .xll application/excel .xll application/vnd.ms-excel .xll application/x-excel .xlm
    * application/excel .xlm application/vnd.ms-excel .xlm application/x-excel .xls application/excel .xls
    * application/vnd.ms-excel .xls application/x-excel .xls application/x-msexcel .xlt application/excel .xlt
    * application/x-excel .xlv application/excel .xlv application/x-excel .xlw application/excel .xlw
    * application/vnd.ms-excel .xlw application/x-excel .xlw application/x-msexcel .xm audio/xm .xml application/xml
    * .xml text/xml .xmz xgl/movie .xpix application/x-vnd.ls-xpix .xpm image/x-xpixmap .xpm image/xpm .x-png image/png
    * .xsr video/x-amt-showrun .xwd image/x-xwd .xwd image/x-xwindowdump .xyz chemical/x-pdb .z application/x-compress
    * .z application/x-compressed .zip application/x-compressed .zip application/x-zip-compressed .zip application/zip
    * .zip multipart/x-zip .zoo application/octet-stream .zsh text/x-script.zsh
    */
}
